/*
 *  Disk.h
 *
 *  CDisk class for direct disk operatoin
 *
 *  Author: Binghua Duan <bhduan@gmail.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 */

#pragma once
#include <winioctl.h>

#pragma pack(1)
typedef struct _PARTENTRY
{
	BYTE            Part_BootInd;           // If 80h means this is boot partition
	BYTE            Part_FirstHead;         // Partition starting head based 0
	BYTE            Part_FirstSector;       // Partition starting sector based 1
	BYTE            Part_FirstTrack;        // Partition starting track based 0
	BYTE            Part_FileSystem;        // Partition type signature field
	BYTE            Part_LastHead;          // Partition ending head based 0
	BYTE            Part_LastSector;        // Partition ending sector based 1
	BYTE            Part_LastTrack;         // Partition ending track based 0
	DWORD           Part_StartSector;       // Logical starting sector based 0
	DWORD           Part_TotalSectors;      // Total logical sectors in partition
} PARTENTRY;

typedef struct _DISK_MBR {
	BYTE Code[440];
	DWORD Signature;
	WORD Zero;
	PARTENTRY Part[4];
	BYTE n55;
	BYTE nAA;
} DISK_MBR;

#pragma pack()

class CDisk
{
public:
	CDisk(LPCTSTR lpszPhyDrv);
	~CDisk();

	BOOL Open(LPCTSTR lpszPhyDrv);
	BOOL Read(LPVOID lpBuffer, UINT nNumberOfBytesToRead);
	BOOL ReadSector(LPVOID lpBuffer, UINT nNumberOfSectorsToRead);
	BOOL Write(LPCVOID lpBuffer, UINT nNumberOfBytesToWrite);
	BOOL WriteSector(LPCVOID lpBuffer, UINT nNumberOfSectorsToWrite);
	BOOL Seek(ULONGLONG nSeekPos);
	BOOL SeekSector(UINT nSector);
	BOOL Eject(); /* eject removable disk */
	BOOL GetGeometry(DISK_GEOMETRY *pdg) const;
	void Close();

	UINT GetTotalSectors() const { return m_nTotalSectors; }
	UINT GetSectorSize() const { return m_nBytesPerSector; }
	BOOL IsValid() const { return m_hPhyDrv != NULL && m_hPhyDrv != INVALID_HANDLE_VALUE; }
	BOOL IsReadOnly() const { return m_bReadOnly; }
	void SetReadOnly(BOOL bReadOnly = TRUE) { m_bReadOnly = bReadOnly; }
protected:
	HANDLE m_hPhyDrv;
	CString m_strPhyDrv;
	UINT m_nBytesPerSector;
	UINT m_nTotalSectors;
	BOOL m_bReadOnly;
};